﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ROrganizer.Client;
using ROrganizer.Client.Files;
using ROrganizer.UI.Controllers.Core;

namespace ROrganizer.UI.Controllers
{
    internal class ProgressFormController
    {
        private readonly AsyncWorker worker;
        private readonly CopyTask[] copyTasks;
        private readonly RemoveTask[] removeTasks;

        public ProgressFormController(CopyTask[] tasks, Action<Exception> exceptioner = null)
        {
            this.copyTasks = tasks;
            this.worker = new AsyncWorker(this.OnChanged, exceptioner: exceptioner);
        }

        public ProgressFormController(RemoveTask[] tasks, Action<Exception> exceptioner = null)
        {
            this.removeTasks = tasks;
            this.worker = new AsyncWorker(this.OnChanged, exceptioner: exceptioner);
        }

        public event EventHandler Changed;
        private void OnChanged()
        {
            if (this.Changed != null)
                this.Changed(this, EventArgs.Empty);
        }

        public bool IsCompleted { get; private set; }
        public int Progress { get; private set; }
        public string Action { get; private set; }
        public string Item { get; private set; }

        public bool IsWorking
        {
            get { return this.worker.IsWorking; }
        }

        public bool CanCancel()
        {
            return this.worker.CanStop;
        }

        public void Cancel()
        {
            this.Action = "Aborting...";
            this.OnChanged();

            this.worker.Stop();
        }

        public void Start()
        {
            if (this.copyTasks != null)
                this.worker.Execute(this.CopyTaskCallback);

            if (this.removeTasks != null)
                this.worker.Execute(this.RemoveTaskCallback);
        }

        private void CopyTaskCallback()
        {
            try
            {
                var processor = new FileProcessor();
                var progress = 0L;
                var total = this.copyTasks.Sum(task => FileEnumerator.GetFileSize(task.Source));

                foreach (var task in this.copyTasks)
                {
                    this.Action = "Copying...";
                    this.Item = task.DestinationName;
                    this.OnChanged();

                    processor.PerformCopy(task, notifier: value => { progress += value; this.Progress = (int)(100 * progress / total); this.OnChanged(); });
                }
            }
            finally
            {
                this.IsCompleted = true;
            }
        }

        private void RemoveTaskCallback()
        {
            try
            {
                var processor = new FileProcessor();
                var progress = 0;
                var total = this.removeTasks.Sum(x => x.Files.Length + x.RelatedFiles.Length);

                foreach (var task in this.removeTasks)
                {
                    this.Action = "Removing...";
                    this.Item = task.Name;
                    this.OnChanged();

                    processor.PerformRemove(task, notifier: file => { this.Progress = 100 * ++progress / total; this.OnChanged(); });
                }
            }
            finally
            {
                this.IsCompleted = true;
            }
        }
    }
}
